﻿

#pragma once


#if FUEL_DEVICE_D3D9


#ifdef _DEBUG
#define D3D_DEBUG_INFO
#endif
#include "ddraw.h"
#include "d3dx9.h"
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, FLIB("d3dx9"))


typedef FVector< D3DVERTEXELEMENT9 > FV_D3DVERTEXELEMENT9;


FINLINE D3DFORMAT FGetD3D9Format(EF_FORMAT fmt)
{
    switch (fmt)
    {
    case eFMT_A8R8G8B8:      return D3DFMT_A8R8G8B8;
    case eFMT_X8R8G8B8:      return D3DFMT_X8R8G8B8;
    case eFMT_A8B8G8R8:      return D3DFMT_A8B8G8R8;
    case eFMT_X8B8G8R8:      return D3DFMT_X8B8G8R8;
    case eFMT_A16B16G16R16:  return D3DFMT_A16B16G16R16;
    case eFMT_A16B16G16R16F: return D3DFMT_A16B16G16R16F;
    case eFMT_A32B32G32R32F: return D3DFMT_A32B32G32R32F;
    case eFMT_D16:           return D3DFMT_D16;
    case eFMT_D32:           return D3DFMT_D32;
    case eFMT_D24S8:         return D3DFMT_D24S8;
    case eFMT_D24X8:         return D3DFMT_D24X8;
    case eFMT_DXT1:          return D3DFMT_DXT1;
    case eFMT_DXT3:          return D3DFMT_DXT3;
    case eFMT_DXT5:          return D3DFMT_DXT5;
    case eFMT_A8L8:          return D3DFMT_A8L8;
    case eFMT_V8U8:          return D3DFMT_V8U8;
    }
    return D3DFMT_A8R8G8B8;
}

FINLINE EF_FORMAT FGetFGEFormat_d3d9(D3DFORMAT fmt)
{
    switch (fmt)
    {
    case D3DFMT_A8R8G8B8:       return eFMT_A8R8G8B8;
    case D3DFMT_X8R8G8B8:       return eFMT_X8R8G8B8;
    case D3DFMT_A8B8G8R8:       return eFMT_A8B8G8R8;
    case D3DFMT_X8B8G8R8:       return eFMT_X8B8G8R8;
    case D3DFMT_A16B16G16R16:   return eFMT_A16B16G16R16;
    case D3DFMT_A16B16G16R16F:  return eFMT_A16B16G16R16F;
    case D3DFMT_A32B32G32R32F:  return eFMT_A32B32G32R32F;
    case D3DFMT_D16:            return eFMT_D16;
    case D3DFMT_D32:            return eFMT_D32;
    case D3DFMT_D24S8:          return eFMT_D24S8;
    case D3DFMT_D24X8:          return eFMT_D24X8;
    case D3DFMT_DXT1:           return eFMT_DXT1;
    case D3DFMT_DXT3:           return eFMT_DXT3;
    case D3DFMT_DXT5:           return eFMT_DXT5;
    case D3DFMT_A8L8:           return eFMT_A8L8;
    case D3DFMT_V8U8:           return eFMT_V8U8;
    }
    return eFMT_A8R8G8B8;
}

FINLINE D3DMULTISAMPLE_TYPE FGetD3D9MultiSample(EF_MULTI_SAMPLE ms)
{
    switch (ms)
    {
    case eMS_Mone:              return D3DMULTISAMPLE_NONE;
    case eMS_NonMaskable:       return D3DMULTISAMPLE_NONMASKABLE;
    case eMS_2_Samples:         return D3DMULTISAMPLE_2_SAMPLES;
    case eMS_3_Samples:         return D3DMULTISAMPLE_3_SAMPLES;
    case eMS_4_Samples:         return D3DMULTISAMPLE_4_SAMPLES;
    case eMS_5_Samples:         return D3DMULTISAMPLE_5_SAMPLES;
    case eMS_6_Samples:         return D3DMULTISAMPLE_6_SAMPLES;
    case eMS_7_Samples:         return D3DMULTISAMPLE_7_SAMPLES;
    case eMS_8_Samples:         return D3DMULTISAMPLE_8_SAMPLES;
    case eMS_9_Samples:         return D3DMULTISAMPLE_9_SAMPLES;
    case eMS_10_Samples:        return D3DMULTISAMPLE_10_SAMPLES;
    case eMS_11_Samples:        return D3DMULTISAMPLE_11_SAMPLES;
    case eMS_12_Samples:        return D3DMULTISAMPLE_12_SAMPLES;
    case eMS_13_Samples:        return D3DMULTISAMPLE_13_SAMPLES;
    case eMS_14_Samples:        return D3DMULTISAMPLE_14_SAMPLES;
    case eMS_15_Samples:        return D3DMULTISAMPLE_15_SAMPLES;
    case eMS_16_Samples:        return D3DMULTISAMPLE_16_SAMPLES;
    }
    return D3DMULTISAMPLE_NONE;
}

FINLINE EF_MULTI_SAMPLE FGetFGEMultiSample_d3d9(D3DMULTISAMPLE_TYPE ms)
{
    switch (ms)
    {
    case D3DMULTISAMPLE_NONE:           return eMS_Mone;
    case D3DMULTISAMPLE_NONMASKABLE:    return eMS_NonMaskable;
    case D3DMULTISAMPLE_2_SAMPLES:      return eMS_2_Samples ;
    case D3DMULTISAMPLE_3_SAMPLES:      return eMS_3_Samples;
    case D3DMULTISAMPLE_4_SAMPLES:      return eMS_4_Samples;
    case D3DMULTISAMPLE_5_SAMPLES:      return eMS_5_Samples;
    case D3DMULTISAMPLE_6_SAMPLES:      return eMS_6_Samples;
    case D3DMULTISAMPLE_7_SAMPLES:      return eMS_7_Samples;
    case D3DMULTISAMPLE_8_SAMPLES:      return eMS_8_Samples;
    case D3DMULTISAMPLE_9_SAMPLES:      return eMS_9_Samples;
    case D3DMULTISAMPLE_10_SAMPLES:     return eMS_10_Samples;
    case D3DMULTISAMPLE_11_SAMPLES:     return eMS_11_Samples;
    case D3DMULTISAMPLE_12_SAMPLES:     return eMS_12_Samples;
    case D3DMULTISAMPLE_13_SAMPLES:     return eMS_13_Samples;
    case D3DMULTISAMPLE_14_SAMPLES:     return eMS_14_Samples;
    case D3DMULTISAMPLE_15_SAMPLES:     return eMS_15_Samples;
    case D3DMULTISAMPLE_16_SAMPLES:     return eMS_16_Samples;
    }
    return eMS_Mone;
}

FINLINE D3DXIMAGE_FILEFORMAT FGetD3D9ImageFormat(EF_IMAGE_FORMAT ffmt)
{
    switch (ffmt)
    {
    case eIF_PNG:      return D3DXIFF_PNG;
    case eIF_JPG:      return D3DXIFF_JPG;
    case eIF_DDS:      return D3DXIFF_DDS;
    }
    return D3DXIFF_PNG;
}

FINLINE EF_IMAGE_FORMAT FGetFGEImageFormat_d3d9(D3DXIMAGE_FILEFORMAT ffmt)
{
    switch (ffmt)
    {
    case D3DXIFF_PNG:      return eIF_PNG;
    case D3DXIFF_JPG:      return eIF_JPG;
    case D3DXIFF_DDS:      return eIF_DDS;
    }
    return eIF_PNG;
}

FINLINE D3DPOOL FGetD3D9Pool(EF_POOL pool)
{
    switch (pool)
    {
    case ePL_Default:   return D3DPOOL_DEFAULT;
    case ePL_Managed:   return D3DPOOL_MANAGED;
    case ePL_SystemMem: return D3DPOOL_SYSTEMMEM;
    case ePL_Scratch:   return D3DPOOL_SCRATCH;
    }
    return D3DPOOL_DEFAULT;
}

FINLINE EF_POOL FGetFGEPool_d3d9(D3DPOOL pool)
{
    switch (pool)
    {
    case D3DPOOL_DEFAULT:   return ePL_Default;
    case D3DPOOL_MANAGED:   return ePL_Managed;
    case D3DPOOL_SYSTEMMEM: return ePL_SystemMem;
    case D3DPOOL_SCRATCH:   return ePL_Scratch;
    }
    return ePL_Default;
}

FINLINE D3DPRIMITIVETYPE FGetD3D9Primitive(EF_PRIMITIVE_TYPE type)
{
    switch (type)
    {
    case ePVT_POINTLIST:     return D3DPT_POINTLIST;
    case ePVT_LINELIST:      return D3DPT_LINELIST;
    case ePVT_LINESTRIP:     return D3DPT_LINESTRIP;
    case ePVT_TRIANGLELIST:  return D3DPT_TRIANGLELIST;
    case ePVT_TRIANGLESTRIP: return D3DPT_TRIANGLESTRIP;
    case ePVT_TRIANGLEFAN:   return D3DPT_TRIANGLEFAN;
    }
    return D3DPT_TRIANGLELIST;
}

FINLINE DWORD FGetD3D9FVF(EF_FVF fvf)
{
    DWORD ret = 0;

    if (fvf & eFVF_XYZ)             ret |= D3DFVF_XYZ;
    if (fvf & eFVF_XYZRHW)          ret |= D3DFVF_XYZRHW;
    if (fvf & eFVF_XYZW)            ret |= D3DFVF_XYZW;
    if (fvf & eFVF_NORMAL)          ret |= D3DFVF_NORMAL;
    if (fvf & eFVF_DIFFUSE)         ret |= D3DFVF_DIFFUSE;
    if (fvf & eFVF_TEX1)            ret |= D3DFVF_TEX1;

    return ret;
}

FINLINE DWORD FGetD3D9Usage(EF_TEXTURE_TYPE tt)
{
    switch (tt)
    {
    case eTT_Default:       return D3DX_DEFAULT;
    case eTT_WriteOnly:     return D3DUSAGE_WRITEONLY;

    case eTT_RenderTarget:  return D3DUSAGE_RENDERTARGET;
    case eTT_DepthStencil:  return D3DUSAGE_DEPTHSTENCIL;
    case eTT_Dynamic:       return D3DUSAGE_DYNAMIC;
    }
    return D3DX_DEFAULT;
}

FINLINE DWORD FGetD3D9TextureLockFlags(EF_TEXTURE_LOCK t)
{
    DWORD ret = 0;
    if (t & eTL_ReadOnly)   ret |= D3DLOCK_READONLY;
    if (t & eTL_Discard)    ret |= D3DLOCK_DISCARD;
    return ret;
}

FINLINE DWORD FGetD3D9ClearFlags(EF_CLEAR_FLAGS cf)
{
    DWORD ret = 0;

    if (cf & eCF_Target)  ret |= D3DCLEAR_TARGET;
    if (cf & eCF_ZBuffer) ret |= D3DCLEAR_ZBUFFER;
    if (cf & eCF_Stencil) ret |= D3DCLEAR_STENCIL;

    return ret;
}

FINLINE D3DDECLUSAGE FGetD3D9DeclUsage(EF_STREAM_TYPE t)
{
    switch (t)
    {
    case eST_POSITION:      return D3DDECLUSAGE_POSITION;
    case eST_NORMAL:        return D3DDECLUSAGE_NORMAL;
    case eST_COLOR:         return D3DDECLUSAGE_COLOR;
    case eST_UV:            return D3DDECLUSAGE_TEXCOORD;
    case eST_TANGENT:       return D3DDECLUSAGE_TANGENT;
    case eST_BLENDINX:      return D3DDECLUSAGE_BLENDINDICES;
    case eST_BLENDWEIGHT2:  return D3DDECLUSAGE_BLENDWEIGHT;
    case eST_BLENDWEIGHT4:  return D3DDECLUSAGE_BLENDWEIGHT;
    }
    FASSERT_STR(_T("数据异常"));
    return D3DDECLUSAGE_POSITION;
}

FINLINE D3DDECLTYPE FGetD3D9DeclType(EF_STREAM_TYPE t)
{
    switch (t)
    {
#if FUEL_RENDER_STREAM_FLOAT16
    case eST_POSITION:      return D3DDECLTYPE_FLOAT16_4;
    case eST_NORMAL:        return D3DDECLTYPE_FLOAT16_4;
    case eST_COLOR:         return D3DDECLTYPE_D3DCOLOR;
    case eST_UV:            return D3DDECLTYPE_FLOAT16_2;
    case eST_TANGENT:       return D3DDECLTYPE_FLOAT16_4;
    case eST_BLENDINX:      return D3DDECLTYPE_UBYTE4;
    case eST_BLENDWEIGHT2:  return D3DDECLTYPE_FLOAT16_2;
    case eST_BLENDWEIGHT4:  return D3DDECLTYPE_FLOAT16_4;
#else
    case eST_POSITION:      return D3DDECLTYPE_FLOAT3;
    case eST_NORMAL:        return D3DDECLTYPE_FLOAT3;
    case eST_COLOR:         return D3DDECLTYPE_D3DCOLOR;
    case eST_UV:            return D3DDECLTYPE_FLOAT2;
    case eST_TANGENT:       return D3DDECLTYPE_FLOAT3;
    case eST_BLENDINX:      return D3DDECLTYPE_UBYTE4;
    case eST_BLENDWEIGHT2:  return D3DDECLTYPE_FLOAT2;
    case eST_BLENDWEIGHT4:  return D3DDECLTYPE_FLOAT4;
#endif
    }
    FASSERT_STR(_T("数据异常"));
    return D3DDECLTYPE_UNUSED;
}

FINLINE void FMakeDecl_d3d9(EF_STREAM_TYPE t, D3DVERTEXELEMENT9& vl, size_t* offset = 0)
{
    if (t == eST_Max)
    {
        vl.Stream = 0xFF;
        vl.Offset = 0;
        vl.Type = D3DDECLTYPE_UNUSED;
        vl.Method = 0;
        vl.Usage = 0;
        vl.UsageIndex = 0;
    }
    else
    {
        vl.Stream = (WORD)t;
        vl.Offset = (WORD)(offset ? *offset : 0);
        vl.Type = (BYTE)FGetD3D9DeclType(t);
        vl.Method = 0;
        vl.Usage = (BYTE)FGetD3D9DeclUsage(t);
        vl.UsageIndex = 0;
        if (offset)
            *offset += FGetStreamSride(t);
    }
}

#endif

